package com.sojson.util.security.shiro.interceptor.core;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.mgt.SecurityManager;
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
import org.springframework.core.annotation.AnnotationUtils;

import com.sojson.util.security.shiro.annotation.Login;

/**
 * 重写:org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor
 * 
 * @author liu
 * @Date 2020-06-12 10:36:09
 * @Description
 *
 */
public class CustomAuthorizationAttributeSourceAdvisor extends StaticMethodMatcherPointcutAdvisor {

    /**
     * 
     */
    private static final long serialVersionUID = 6058088802761266752L;

    // TODO
    /** shiro默认拦截的注解 */
    // @SuppressWarnings("unchecked")
    // private static final Class<? extends Annotation>[] AUTHZ_ANNOTATION_CLASSES = new Class[] { RequiresPermissions.class,
    // RequiresRoles.class, RequiresUser.class, RequiresGuest.class, RequiresAuthentication.class };
    /** 自定义拦截的注解 */
    @SuppressWarnings("unchecked")
    private static final Class<? extends Annotation>[] AUTHZ_ANNOTATION_CLASSES =
        new Class[] {RequiresPermissions.class, RequiresRoles.class, Login.class};

    protected SecurityManager securityManager = null;

    /**
     * 项目初始化期执行
     */
    public CustomAuthorizationAttributeSourceAdvisor() {
        // 之前创建的是:org.apache.shiro.spring.security.interceptor.AopAllianceAnnotationsAuthorizingMethodInterceptor
        setAdvice(new CustomAddAuthorizingAnnotationMethodInterceptor());

    }

    /**
     * 如果要调用的方法或类上有AUTHZ_ANNOTATION_CLASSES中的注解就执行这个方法
     * 
     * 如果返回true就用对应的拦截器进行拦截并处理,如果返回false就通过
     */
    @Override
    public boolean matches(Method method, Class<?> targetClass) {
        // TODO
        return isAuthzAnnotationPresent(method)
            || (targetClass == null ? false : isAuthzAnnotationPresent(targetClass));

        // Method m = method;
        // if (isAuthzAnnotationPresent(m)) {
        // return true;
        // }
        //
        // if (targetClass != null) {
        // try {
        // m = targetClass.getMethod(m.getName(), m.getParameterTypes());
        // return isAuthzAnnotationPresent(m) || isAuthzAnnotationPresent(targetClass);
        // } catch (NoSuchMethodException ignored) {
        // // default return value is false. If we can't find the method, then obviously
        // // there is no annotation, so just use the default return value.
        // }
        // }
        // return false;
    }

    /**
     * 如果类包含某个注解,就返回true,否则返回false
     * 
     * @param method
     * @return
     */
    private boolean isAuthzAnnotationPresent(Class<?> targetClazz) {
        for (Class<? extends Annotation> annClass : AUTHZ_ANNOTATION_CLASSES) {
            Annotation a = AnnotationUtils.findAnnotation(targetClazz, annClass);
            if (a != null) {
                return true;
            }
        }
        return false;
    }

    /**
     * 如果方法包含某个注解,就返回true,否则返回false
     * 
     * @param method
     * @return
     */
    private boolean isAuthzAnnotationPresent(Method method) {
        for (Class<? extends Annotation> annClass : AUTHZ_ANNOTATION_CLASSES) {
            Annotation a = AnnotationUtils.findAnnotation(method, annClass);
            if (a != null) {
                return true;
            }
        }
        return false;
    }

    /** Get方法 */
    public SecurityManager getSecurityManager() {
        return securityManager;
    }

    /** Set方法 */
    public void setSecurityManager(SecurityManager securityManager) {
        this.securityManager = securityManager;
    }

}
